import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.util.Arrays;

import com.speljohan.rsbot.accessors.NPC;
import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.script.Constants;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.wrappers.RSInterface;
import com.speljohan.rsbot.script.wrappers.RSNPC;
import com.speljohan.rsbot.script.wrappers.RSObject;
import com.speljohan.rsbot.script.wrappers.RSTile;

public class DMagic extends Script implements PaintListener {
	public int[] axes = { 1349, 1351, 1353, 1355, 1357, 1359, 6739 };

	int waitAfterMoving = -1;

	int failCount = 0;

	RSNPC ent;

	int ENT = 0;

	boolean cameraMoving = false;

	int loads = 0;

	boolean spinningView = false;

	int[] treeID = new int[] { 1306 };

	public RSTile[] treesToBankPath = {

	new RSTile(2697, 3425), new RSTile(2708, 3436), new RSTile(2712, 3452),
			new RSTile(2722, 3461), new RSTile(2725, 3476),
			new RSTile(2726, 3492), };

	public RSTile[] bankToTreesPath = reversePath(treesToBankPath);

	public RSTile tree1Tile = new RSTile(2695, 3424);

	public RSTile tree2Tile = new RSTile(2695, 3424);

	public int bankerID = 495;

	public RSTile bankTile = new RSTile(2726, 3492);

	public RSTile centerTile = new RSTile(2695, 3424);

	public final String[] treeNames = { "Willow" };

	public RSTile[] walkBackPath = { new RSTile(3229, 3219),
			new RSTile(3229, 3232), new RSTile(3221, 3244),
			new RSTile(3206, 3246), new RSTile(3191, 3246),
			new RSTile(3176, 3245), new RSTile(3161, 3246),
			new RSTile(3145, 3250), new RSTile(3129, 3251),
			new RSTile(3113, 3248), new RSTile(3098, 3250),
			new RSTile(3093, 3246) };

	public boolean atBank() {
		return distanceTo(bankTile) < 15;
	}

	public boolean attackedByEnt() {
		ent = null;
		ent = getNearestNPCByName("Willow");
		if (ent == null || getMyPlayer().getInteracting() == null) {
			return false;
		}
		return getMyPlayer().getInteracting().equals(ent);
	}

	public boolean atTrees() {
		return distanceTo(tree1Tile) < 10 || distanceTo(tree2Tile) < 10;
	}

	public int bank() {
		if (atBank()) {
			if (RSInterface.getInterface(Constants.INTERFACE_BANK).isValid()) {
				bank.depositAllExcept(1349, 1351, 1353, 1355, 1357, 1359, 6739);
				loads++;
				return random(500, 800);
			} else {
				runOn();
				if (distanceTo(bankTile) > 0) {
					if (dpWalkTile(bankTile)) {
						waitAfterMoving = random(200, 300);
						return random(500, 800);
					} else {
						return -1;
					}
				} else {
					if (useBanker()) {
						return random(500, 800);
					} else {
						return -1;
					}
				}
			}
		} else {
			if (treesToBank()) {
				return random(500, 800);
			} else {
				return -1;
			}
		}
	}

	public boolean bankToTrees() {
		return dpWalkPath(bankToTreesPath);
	}

	public boolean checkAttack() {
		if (getMyPlayer().isInCombat()) {
			return runFromCombat();
		} else {
			return false;
		}
	}

	public boolean checkCamera() {
		if (cameraMoving) {
			if (Bot.getClient().getCameraCurveY() >= 380) {
				Bot.getInputManager().releaseKey((char) KeyEvent.VK_UP);
				cameraMoving = false;
			}
			return true;
		} else if (Bot.getClient().getCameraCurveY() < 380) {
			Bot.getInputManager().pressKey((char) KeyEvent.VK_UP);
			cameraMoving = true;
			return true;
		}
		return false;
	}

	public void checkEnt() {
		ent = null;
		ent = getNearestNPCByName("Willow");
		if (getMyPlayer().getInteracting().equals(ent)) {
			atTile(getMyPlayer().getLocation(), "walk here");
		}

	}

	public boolean checkForEnt() {
		// taken and modified from dontpanic ( Taken from Tenac's willowcutter.)
		if (getMyPlayer().getInteracting() != null) {
			final int count = Bot.getClient().getNPCCount();
			final NPC[] npcs = Bot.getClient().getNPCArray();
			final int[] ints = Bot.getClient().getNPCIndexArray();
			for (int i = 0; i < count; i++) {
				final RSNPC npc = new RSNPC(npcs[ints[i]]);
				if (getMyPlayer().getInteracting().equals(npc)
						&& Arrays.asList("Magic tree").contains(npc.getName())) {
					atTile(getMyPlayer().getLocation(), "alk here");

					return true;
				}
			}
		}
		return false;
	}

	public boolean checkSpinningView() {
		if (spinningView) {
			Bot.getInputManager().releaseKey((char) KeyEvent.VK_RIGHT);
			spinningView = false;
			return true;
		} else {
			return false;
		}
	}

	public int chop() {
		if (atTrees()) {
			final int result = clickTree();
			if (result > 0) {
				if (result == 1) {
					waitAfterMoving = random(500, 800);
				}
				return random(500, 800);
			} else {
				if (result == -1) {
					spinView();
				} else {
					if (distanceTo(centerTile) > 3) {
						final RSTile rCenterTile = new RSTile(centerTile.getX()
								+ random(-2, 2), centerTile.getY()
								+ random(-2, 2));
						dpWalkTile(rCenterTile);
					}
				}
				return random(500, 800);
			}
		} else {
			if (bankToTrees()) {
				return random(500, 800);
			} else {
				return -1;
			}
		}
	}

	public int clickTree() {
		final RSObject object = findObject(treeID);
		if (object == null || distanceTo(object.getLocation()) > 16) {
			return -2;
		}
		if (atTree(object, "Chop")) {
			return 1;
		}
		if (distanceTo(object.getLocation()) > 3) {
			if (dpWalkTile(object.getLocation())) {
				return 2;
			}
		}
		return -1;
	}

	public boolean dpWalkPath(final RSTile[] path) {
		for (int i = path.length - 1; i >= 0; i--) {
			if (dpWalkTile(path[i])) {
				return true;
			}
		}
		return false;
	}

	public boolean dpWalkTile(final RSTile tile) {
		if (distanceTo(tile) <= 16) {
			walkTileMM(tile);
			return true;
		} else {
			return false;
		}
	}

	@Override
	public String getAuthor() {
		return "Dwu + Dontpanic for the scriptbase, I only his script modified it to do Magics :>";
	}

	@Override
	public String getName() {
		return "DwuMagic";
	}

	@Override
	public String getScriptCategory() {
		return "Woodcutting";
	}

	@Override
	public String getScriptDescription() {
		String html = "";

		html += "<html>n";
		html += "<body>n";
		html += "<h2>" + getName() + " v" + getVersion() + "</h2><br>n";
		html += "Author: " + getAuthor() + "<br><br>n";
		html += "Chops & banks oaks at Draynor.<br><br>";
		// html += "<center>n";
		// html += "Arguments:<input type="text" name="args">n";
		// html += "</center>n";
		html += "</body>n";
		html += "</htmln";

		return html;
	}

	@Override
	public double getVersion() {
		return 1.2;
	}

	public void homeTele() {
		openTab(Constants.TAB_MAGIC);
		castSpell(1);
	}

	@Override
	public int loop() {

		if (!isLoggedIn()) {
			return random(100, 200);
		}
		if (checkSpinningView()) {
			return random(200, 300);
		}

		if (checkForEnt()) {
			return random(100, 200);
		}
		if (checkCamera()) {
			return random(500, 800);
		}
		if (getMyPlayer().isMoving()) {
			return random(150, 200);
		}
		if (waitAfterMoving != -1) {
			final int toReturn = waitAfterMoving;
			waitAfterMoving = -1;
			return toReturn;
		}
		if (checkAttack()) {
			return random(800, 1000);
		}
		if (getMyPlayer().getAnimation() != -1) {
			return random(150, 200);
		}
		final int result = work();
		if (result != -1) {
			failCount = 0;
			return result;
		}
		if (walkBack()) {
			failCount = 0;
			return random(500, 800);
		}

		failCount++;
		if (failCount >= 10) {
			failCount = 0;
			homeTele();
			return random(2000, 3000);
		}
		return random(1000, 2000);
	}

	@Override
	public void onFinish() {
		Bot.getEventManager().removeListener(PaintListener.class, this);
	}

	public void onRepaint(final Graphics g) {
		g.setColor(Color.BLACK);
		g.drawString("Dwu's Magic's", 260, 20);
		g.drawString("Loads: " + loads, 260, 38);
	}

	@Override
	public boolean onStart(final String[] args) {
		return true;
	}

	public boolean runFromCombat() {
		if (atBank()) {
			bankToTrees();
			return true;
		}
		if (atTrees()) {
			treesToBank();
			return true;
		}
		return false;
	}

	public void runOn() {
		setRun(true);
	}

	public void spinView() {
		Bot.getInputManager().pressKey((char) KeyEvent.VK_RIGHT);
		spinningView = true;
	}

	public boolean treesToBank() {
		return dpWalkPath(treesToBankPath);
	}

	public boolean useBanker() {
		final RSNPC npc = getNearestNPCByID(bankerID);
		return atNPC(npc, "Bank Banker");
	}

	public boolean walkBack() {
		return dpWalkPath(walkBackPath);
	}

	public int work() {
		if (getInventoryCount() != 28) {
			return chop();
		} else {
			return bank();
		}
	}

}